package com.chendx.store.goods.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chendx.model.behivor.pojo.UserFocus;
import com.chendx.model.common.dtos.ResponseResult;
import com.chendx.model.common.enums.AppHttpCodeEnum;
import com.chendx.model.goods.dto.SkuDto;
import com.chendx.model.goods.dto.SkuInfoDto;
import com.chendx.model.goods.pojo.Category;
import com.chendx.model.goods.pojo.Sku;
import com.chendx.model.goods.pojo.Spu;
import com.chendx.model.goods.vo.GoodsNotice;
import com.chendx.model.goods.vo.SkuInfoVo;
import com.chendx.model.order.pojo.OrderItem;
import com.chendx.model.user.pojo.User;
import com.chendx.store.common.constants.goods.GoodsConstants;
import com.chendx.store.common.entity.IdWorker;
import com.chendx.store.goods.feign.BehaviorFeign;
import com.chendx.store.goods.mapper.CategoryMapper;
import com.chendx.store.goods.mapper.SkuMapper;
import com.chendx.store.goods.mapper.SpuMapper;
import com.chendx.store.goods.service.SkuService;
import com.chendx.store.utils.AppThreadLocalUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by chendx on 2022/4/18.
 */
@Service
public class SkuServiceImpl extends ServiceImpl<SkuMapper,Sku> implements SkuService {
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private BehaviorFeign behaviorFeign;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Override
    public ResponseResult decrCount(OrderItem orderItem) {
        int count = skuMapper.decrCount(orderItem);
        if (count < 0) {
            throw new RuntimeException("减少库存失败");
        }
        Sku sku = new Sku();
        sku.setId(orderItem.getSkuId());
        rabbitTemplate.convertAndSend(GoodsConstants.SKU_UPDATE_TOPIC,"",JSON.toJSONString(sku));
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult incrCount(OrderItem orderItem) {
        int count = skuMapper.incrCount(orderItem);
        if (count < 0) {
            throw new RuntimeException("库存回滚失败");
        }
        Sku sku = new Sku();
        sku.setId(orderItem.getSkuId());
        rabbitTemplate.convertAndSend(GoodsConstants.SKU_UPDATE_TOPIC,"",JSON.toJSONString(sku));
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult updatePrice(SkuDto dto) {
        if (dto == null || dto.getSkuId() == null || dto.getPrice() <= 0 ){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.checkParam();
        Sku sku = getById(dto.getSkuId());
        if (sku == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.SKU_NOT_EXIST);
        }
        //未修改前的价格
        Integer beforePrice = sku.getPrice();
        int count = skuMapper.updatePrice(dto);
        if (count > 0){
            if (beforePrice > dto.getPrice()){
                System.out.println("商品降价通知");
                List<UserFocus> userFocuses = behaviorFeign.focusUser(String.valueOf(sku.getId()));
                if (userFocuses == null || userFocuses.size() <= 0){
                    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
                }
                List<String> usernames = userFocuses.stream().map(userFocus -> userFocus.getUserName()).collect(Collectors.toList());
                BigDecimal bigDecimal = new BigDecimal((beforePrice - dto.getPrice()) / 100);
                GoodsNotice goodsNotice = new GoodsNotice();
                goodsNotice.setTitle("商品降价通知");
                goodsNotice.setId(idWorker.nextId() + "");
                goodsNotice.setSkuId(dto.getSkuId());
                goodsNotice.setSpuId(String.valueOf(sku.getSpuId()));
                goodsNotice.setContent("你关注的商品降价了 ￥" +  bigDecimal.setScale(2, RoundingMode.HALF_UP) + "元");
                goodsNotice.setCreateTime(new Date());
                goodsNotice.setSkuImg(sku.getImage());
                goodsNotice.setSkuTitle(sku.getName());
                goodsNotice.setState("0");
                for (String username : usernames){
                    redisTemplate.boundHashOps(GoodsConstants.GOODS_NOTICE_USER + username).put(sku.getId().toString(), JSON.toJSONString(goodsNotice));
                }
                rabbitTemplate.convertAndSend("sku_focus",dto.getSkuId(), dto.getPrice());
            }
            //发送rabbit
            rabbitTemplate.convertAndSend(GoodsConstants.SKU_UPDATE_TOPIC,"",JSON.toJSONString(sku));
            return ResponseResult.okResult(dto.getPrice());
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
    }

    @Override
    public ResponseResult noReadNotice() {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        Object obj = redisTemplate.boundHashOps(GoodsConstants.NO_READ_GOODS_NOTICE).get(username);
        if (obj == null){
            return ResponseResult.okResult(0);
        }
        int count = Integer.parseInt(String.valueOf(obj));
        return ResponseResult.okResult(count);
    }

    @Override
    public ResponseResult notice() {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        List<Object> values = redisTemplate.boundHashOps(GoodsConstants.GOODS_NOTICE_USER + username).values();
        if (values == null){
            return ResponseResult.okResult(AppHttpCodeEnum.NO_NOTICE);
        }
        List<GoodsNotice> goodsNotices = JSON.parseArray(values.toString(), GoodsNotice.class);
        goodsNotices.sort(new Comparator<GoodsNotice>() {
            @Override
            public int compare(GoodsNotice o1, GoodsNotice o2) {
                return o2.getCreateTime().compareTo(o1.getCreateTime());
            }
        });
        return ResponseResult.okResult(goodsNotices);
    }

    @Override
    public ResponseResult read() {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        List<Object> values = redisTemplate.boundHashOps(GoodsConstants.GOODS_NOTICE_USER + username).values();
        if (values == null || values.size() == 0){
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_NOTICE);
        }
        List<GoodsNotice> goodsNotices = JSON.parseArray(values.toString(), GoodsNotice.class);
        for (GoodsNotice goodsNotice : goodsNotices){
            if (goodsNotice.getState().equals("0")){
                goodsNotice.setState("1");
                redisTemplate.boundHashOps(GoodsConstants.GOODS_NOTICE_USER  + username).put(goodsNotice.getSkuId(),JSON.toJSONString(goodsNotice));
            }
        }
        redisTemplate.boundHashOps(GoodsConstants.NO_READ_GOODS_NOTICE).delete(username);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult skuInfos(SkuDto dto) {
        if (dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        LambdaQueryWrapper<Sku> queryWrapper = new LambdaQueryWrapper<>();
        if (!StringUtils.isEmpty(dto.getSpuId())){
            queryWrapper.eq(Sku::getSpuId,dto.getSpuId());
        }
        dto.checkParam();
        List<Sku> skuList = list(queryWrapper);
        List<SkuInfoVo> skuInfoVos = new ArrayList<>();
        for (Sku sku : skuList){
            SkuInfoVo skuInfoVo = new SkuInfoVo();
            BeanUtils.copyProperties(sku,skuInfoVo);
            skuInfoVo.setId(String.valueOf(sku.getId()));

            Spu spu = spuMapper.selectById(sku.getSpuId());
            Category category1 = categoryMapper.selectById(spu.getCategory1Id());
            skuInfoVo.setCategory1Name(category1.getName());
            Category category2 = categoryMapper.selectById(spu.getCategory2Id());
            skuInfoVo.setCategory2Name(category2.getName());
            skuInfoVos.add(skuInfoVo);
        }
        return ResponseResult.okResult(skuInfoVos);
    }

    @Override
    public ResponseResult add(SkuInfoDto dto) {
        if (dto == null || dto.getSpuId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        Sku sku = new Sku();
        BeanUtils.copyProperties(dto,sku);
        sku.setSn("NO.123123");
        sku.setCreateTime(new Date());
        sku.setUpdateTime(new Date());
        sku.setSaleNum(0);
        sku.setCommentNum(0);
        sku.setStatus("1");
        boolean save = save(sku);
        if (save){
            System.out.println("发送rabbitmq");
          rabbitTemplate.convertAndSend(GoodsConstants.SKU_ADD_TOPIC,null,sku.getId() +":"+sku.getSpuId());
          return ResponseResult.okResult(sku);
        }else{
            return ResponseResult.okResult(AppHttpCodeEnum.SERVER_ERROR);
        }
    }

}
